#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import json
import threading
import time
import hashlib


class TradeType(object):
    BUY = '买入'
    SELL = '卖出'


class StrageType(object):
    ONE = "不拆单"
    TWO = "DMA直接切分"
    THREE = "DMA算法交易引擎"
    FOUR = "DPA发送至暗池"
    FIVE = "Immediate or Cancel"


class ChannelType(object):
    ONE = "交易所"
    TWO = "暗池"
    THREE = "Inner Deal"

AUTO_TRADE_TIME = 5
DEAL_PERCENT = 5

class TradeInfo(object):
    def __init__(self, stock_id, trade_type, trade_price, quantity, strage, channel,stock_name):
        self.stock_id = stock_id
        self.strage = strage
        self.trade_type = trade_type
        self.channel = channel
        self.trade_price = trade_price
        self.quantity = quantity
        self.start_time = time.time()
        self.deal_percent = 0
        self.stock_name=stock_name
        self.trade_info_id = hashlib.md5(
            bytes(str(time.time()), encoding='utf-8')).hexdigest()

    @staticmethod
    def obj_2_json(self):
        return {
            'stock_id': self.stock_id,
            'trade_type': self.trade_type,
            'trade_price': self.trade_price,
            'quantity': self.quantity,
            'start_time': self.start_time,
            'trade_info_id': self.trade_info_id,
            "strage": self.strage,
            "channel": self.channel,
            'deal_percent': self.deal_percent,
            'stock_name' : self.stock_name
        }


class ClientInfo(object):

    def __init__(self, client_id):
        self.client_id = client_id
        self.frozen_assets = 0
        self.available_assets = 1e6  # 初始1百万
        self.total_market_value = 0
        self.stock_info = {}
        self.trade_info = {}

    @property
    def total_asset(self):
        return self.frozen_assets + self.available_assets + self.total_market_value

    @staticmethod
    def obj_2_json(self):
        return {
            'client_id': self.client_id,
            'frozen_assets': self.frozen_assets,
            'available_assets': self.available_assets,
            'total_market_value': self.total_market_value,
            'total_asset': self.total_asset,
            'stock_info': self.stock_info,
            'trade_info': json.dumps(self.trade_info, default=TradeInfo.obj_2_json),
        }

    def check_trade_info(self, trade_info):
        if trade_info.trade_type == TradeType.SELL:
            if self.stock_info.get(trade_info.stock_id, 0) < trade_info.quantity:
                return 'current stock quantity is not enough!'
        elif trade_info.trade_type == TradeType.BUY:
            total_trade_value = trade_info.trade_price * trade_info.quantity
            if self.available_assets < total_trade_value:
                return 'current available_assets is not enough!'

        return 'success'

    def add_trade_info(self, trade_info):
        self.trade_info[trade_info.trade_info_id] = trade_info
        total_trade_value = trade_info.trade_price * trade_info.quantity
        if trade_info.trade_type == TradeType.BUY:
            # add的时候先计算冻结金额
            self.frozen_assets += total_trade_value
            self.available_assets -= total_trade_value

    def deal_trade(self, trade_info_id, percent):
        trade_info = self.trade_info[trade_info_id]
        trade_info.deal_percent += percent
        trade_quantity = trade_info.quantity * percent / 100.0
        total_trade_value = trade_info.trade_price * trade_quantity
        if trade_info.trade_type == TradeType.BUY:
            self.frozen_assets -= total_trade_value
            self.total_market_value += total_trade_value
            self.stock_info[trade_info.stock_id] = self.stock_info.get(
                trade_info.stock_id, 0) + trade_quantity
        elif trade_info.trade_type == TradeType.SELL:
            self.available_assets += total_trade_value
            self.total_market_value -= total_trade_value
            self.stock_info[trade_info.stock_id] = self.stock_info.get(
                trade_info.stock_id, 0) - trade_quantity
        if trade_info.deal_percent >= 100:
            return
            # self.trade_info.pop(trade_info_id)
        else:
            timer = threading.Timer(AUTO_TRADE_TIME, lambda: self.deal_trade(trade_info_id, DEAL_PERCENT))
            timer.start()


class UserHandler(object):

    def __init__(self):
        self.client_info = {}

    def user_login(self, client_id):
        if client_id not in self.client_info:
            self.create_user(client_id)

        client_info = self.client_info[client_id]
        return json.dumps(client_info, default=ClientInfo.obj_2_json)

    def get_client_info(self, client_id):
        client_info = self.client_info.get(client_id)
        return json.dumps(client_info, default=ClientInfo.obj_2_json)

    def create_user(self, client_id):
        self.client_info[client_id] = ClientInfo(client_id)

    def add_trade_info(self, client_id, trade_info):
        if client_id not in self.client_info:
            return 'no client info %s' % client_id

        result = self.client_info[client_id].check_trade_info(trade_info)
        print(result)
        if result == 'success':
            self.client_info[client_id].add_trade_info(trade_info)
            timer = threading.Timer(AUTO_TRADE_TIME, lambda: self.client_info[client_id].deal_trade(trade_info.trade_info_id, DEAL_PERCENT))
            timer.start()

        return result
